import React from 'react';
import { notification, Icon } from 'antd';
import { Toast } from 'antd-mobile';

import Zcon from '@cbd/icon';
import router from "umi/router";

const delay = (timeout) => new Promise(resolve => setTimeout(resolve, timeout));

const getViewPortHeight = () => {
  const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
  return clientHeight;
}

const openNotificationWithIconPhone = (type, message) => {
  const obj = {
    error: 'fail',
    success: 'success',
    warning: 'info',
  };
  const method = obj[type];
  if (method) {
    Toast[method](message);
  }
};

const openNotificationWithIcon = (type, message, description) => {
  const obj = {
    error: {
      className: 'notification__custom notification__error',
      icon: <Zcon type="close-circle" style={{ color: '#ff0000' }} />,
    },
    success: {
      className: 'notification__custom notification__success',
      icon: <Icon type="check-circle" theme="filled" style={{ color: '#00c637' }} />,
    },
    warning: {
      className: 'notification__custom notification__warning',
      icon: <Icon type="exclamation-circle" theme="filled" style={{ color: '#ffa800' }} />,
    },
  };
  const { className = '', icon = '' } = obj[type] || {};
  notification[type]({
    className,
    message,
    description,
    icon,
    // duration: null,
  });
};

const getUuid = (prefix) => {
  const s = [];
  const hexDigits = "0123456789abcdefghijklmnopqrstuvwsyz";
  for (let index = 0; index < 36; index += 1) {
    s[index] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }
  s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] && 0x3) || 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = "_";
  s[13] = "_";
  s[18] = "_";
  s[23] = "_";
  const uuid = s.join("");
  return prefix ? `${prefix}_${uuid}` : uuid;
};

const getSubFieldCol = (preId, num = 1) => {
  const newArr = [];
  for (let i = 0; i < num; i += 1) {
    newArr.push({
      id: getUuid('fieldChild'),
      preId,
      content: [],
    });
  }
  return newArr;
}
const setActiveMenu = (menuKey, openMenuKey, _dispatch) => {
  let dispatch = _dispatch;
  if (!dispatch) {
    if (window.g_app && window.g_app._store) {
      // eslint-disable-next-line
      dispatch = window.g_app._store.dispatch;
    }
  }
  if (dispatch) {
    dispatch({
      type: 'Public/set/openMenuKeys',
      payload: openMenuKey ? [openMenuKey] : [],
    });
    dispatch({
      type: 'Public/set/selectedMenuKeys',
      payload: menuKey ? [menuKey] : [],
    });
  }
}
const goToUrl = (url, menuKey, openMenuKey, _dispatch) => {
  router.push(url);
  setActiveMenu(menuKey, openMenuKey, _dispatch);
}

const omit = (obj = {}, keys = []) => {
  const res = {};
  Object.keys(obj).forEach((key) => {
    if (!keys.includes(key)) {
      res[key] = obj[key];
    }
  });
  return res;
};

const getOrgName = (item, defaultName = '') => {
  let res = defaultName;
  if (item) {
   res = (item.extentAttributes || item.extentAttribute || {}).ORG_NAME; 
  }

  return res || defaultName;
}

const _getOrgArrs = (data, code, indexArray) => {
  const arr = Array.from(indexArray);
  for (let i = 0, len = data.length; i < len; i += 1) {
    arr.push(getOrgName(data[i]));
    if (data[i].code === code) {
      // arr.pop();
      return arr;
    }

    const { children } = data[i];
    if (children && children.length) {
      const result = _getOrgArrs(children, code, arr);
      if (result) return result;
    }
    arr.pop();
  }
  return false;
};
const getOrgArrs = (data, code, indexArray) => {
  const result = _getOrgArrs(data, code, indexArray);
  if (result && result.length > 0) {
    // 去除重复的root组织
    result.shift();
  }
  return result;
}

const updateNoticeUser = (selectUsers, noticeUsers, add) => {
  const result = [];

  if (add) { // add all SelectUsers to noticeUsers as result, with duplicates removed
    const currentNoticeCodeMap = (noticeUsers || []).reduce((map, item) => {
      map[item.userCode] = true;
      result.push(item);
      return map;
    }, {});

    (selectUsers || []).forEach((item) => {
      if (!currentNoticeCodeMap[item.key]) {
        result.push({
          ...item,
          userCode: item.key,
          userName: item.props.title,
          userOrgDesc: item.props?.orgsArr?.join('/'),
        })
      }
    })
  } else { // filter from noticeUsers that are not in selectUsers as result
    const currentUserCodeMap = (selectUsers || []).reduce((map, item) => {
      map[item.key] = true;
      return map;
    }, {});

    (noticeUsers || []).forEach((item) => {
      if (!currentUserCodeMap[item.userCode]) {
          result.push(item);
      }
    });
  }

  return result;
}

const getCardChildProperties = (cardProperty) => {
  /* 目前formily-editor@0.0.28生成的card的property结构:
  {
    'x-component': 'Card',
    properties: { // Card 的properties只有一个grid
      'cardgrid_uuid_xxx': {
        'x-component': 'Grid',
        properties: { // getCardChildProperties返回这个properties
          // 子组件的配置在这里
        },
        // ...这里忽略其他的属性
      }
    },
    // ...这里忽略其他的属性
  }
  */
  try {
    const gridSetting = cardProperty.properties[Object.keys(cardProperty.properties)[0]]
    return gridSetting.properties;
  } catch(e) {
    // 编辑器生成的Card格式与当前处理不兼容，需要修改try block中的代码
    window.console.error('Generated Card properties error');
    return {};
  }
}

const formEditorToFormilyFormatter = {
  // arrayTable schema具体格式可以参照
  // src/components/formily/form-editor/widgetConfig/components/ColumnSettingArrayTable
  // 中的schema
  arrayTable(editorConfig) {
    const { 'x-component-props': props } = editorConfig;
    const formilyConfig = {
      ...editorConfig,
      type: 'array',
      title: props.label,
      'x-props': {
        'labelCol': { span: 0 },
        'wrapperCol': { span: 24 },
        'colon': false,
      },
      'x-component-props': {
      },
      items: {
        'type': 'object',
        properties: (props.items || []).reduce((prop, item, index) => {
          const { key, type, title, options } = item;
          prop[key] = {
            key,
            name: key,
            'x-component': type,
            'x-index': index,
            title,
          };
          if (type === 'input') {
            prop[key]['x-component-props'] = {
              maxLength: 20,
            };
          } else if (type === 'select') {
            prop[key].enum = (options || '' ).split(',').map(v => ({ label: v, value: v }));
          }
          return prop;
        }, {}),
      },
    };
    return formilyConfig
  },
};

// 编辑器返回的schema -> formily渲染需要的shcema
const transformEditorToFormily = (formConfigData, isPhone) => {
  const { properties: prevProperties = {} } = formConfigData;
  const indexInfo = [];
  let property;
  let oldIndex;
  let baseIndex;
  let newFormConfigData = { ...formConfigData, properties: {...prevProperties } };

  const { properties } = newFormConfigData;
  const arr = Object.keys(properties);

  if (arr.length > 0) {
    for (const key of arr) {
      property = properties[key];
      if (
        property['x-component'] === 'Grid' &&
        property.properties
      ) {
        indexInfo.push([
          property['x-index'],
          Object.keys(property.properties).length - 1,
        ]);
      } else if (
        property['x-component'] === 'Card'
      ) {
        property['x-component-props'].title = property['x-component-props'].title ||
          property['x-component-props'].label;
        /*
        // card组件只渲染一个，所以不用更新后面表单域的x-index
        try {
          const gridSetting = property.properties[Object.keys(property.properties)[0]]
          indexInfo.push([
            property['x-index'],
            Object.keys(gridSetting.properties).length - 1,
          ]);
        } catch(e) {
          // 编辑器生成的Card格式与当前处理不兼容，需要修改try block中的代码
          window.console.error('Generated Card properties error');
        }
        */
      } else if (
        property['x-component'] === 'arrayTable'
      ) {
        properties[key] = formEditorToFormilyFormatter.arrayTable(property);
      }
    }

    // phone版需要扁平化grid(包括card中默认生成的grid)并更新x-index
    if (!isPhone) {
      return newFormConfigData;
    }

    // indexInfo 可能为空数组
    indexInfo.sort((a, b) => a[0] - b[0]);
    indexInfo.reduce((prev , cur) => {
      cur[1] += prev;
      return cur[1];
    }, 0);

    const newProperties = {};
    const lastIndex = indexInfo.length - 1;
    const updateBaseIndex = () => {
      baseIndex = oldIndex;
      for(let i = lastIndex; i > -1; i-=1) {
        if (indexInfo[i][0] < oldIndex) {
          baseIndex += indexInfo[i][1];
          break;
        }
      }
    }
    for (const key of arr) {
      property = properties[key];
      oldIndex = property['x-index'];
      updateBaseIndex();
      if (
        property['x-component'] === 'Grid'
      ) { 
        // 不渲染grid，grid有几个子组件渲染几个组件，grid后面的组件的x-index要根据这里渲染了
        // 多少个组件而相应增加
        const { properties: innerProperties = {} } = property;
        for(const innerKey of (Object.keys(innerProperties) || [])) {
          newProperties[innerKey] = {
            ...innerProperties[innerKey],
            'x-index': innerProperties[innerKey]['x-index'] + baseIndex,
          };
        }
      } else if (property['x-component'] === 'Card') {
        // 渲染一个card组件，但忽略里层的grid，把grid所有子组件直接渲染在
        // card中
        newProperties[key] = {
          ...property,
          properties: getCardChildProperties(property),
          'x-index': baseIndex,
        }
      } else {
        newProperties[key] = {
          ...property,
          'x-index': baseIndex,
        };
      }
    }
    newFormConfigData = {
      type: 'object',
      properties: newProperties,
    };
}
  // console.log('old', formConfigData, 'new', newFormConfigData); 
  return newFormConfigData;
};

const isPhone = () => window.location.pathname.startsWith('/embedded/phone');

const themeId = 'FLOW_THEME';
// #013460 color
const highlightColor = 'rgba(92, 92, 193, 0.46)';
const borderColor = 'rgba(255,255,255,0.1)';
const borderValue = `1px solid ${borderColor}`;
const updateTheme = (color, strongColor, background, bodyBg = 'rgba(1, 52, 96, .6)') => {
  window.FLOW_THEME = {
    color,
    strongColor,
    backgroundColor: background,
    ligtBackgroundColor: bodyBg,
    highlightColor,
    borderColor,
  };
  let style = document.querySelector(`#${themeId}`);
  if (!style) {
    style = document.createElement('style');
    style.id = themeId;
    document.head.append(style);

  }
  style.innerHTML = 
`
.ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu-title:hover,
.ant-upload-list-item:hover .ant-upload-list-item-info,
.ant-select-tree li .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected,
.ant-steps-item-wait .ant-steps-item-icon,
.ant-table-tbody>tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td, .ant-table-tbody>tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td, .ant-table-thead>tr.ant-table-row-hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td, .ant-table-thead>tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)>td,
.ant-tree.ant-tree-directory .ant-tree-child-tree>li span.ant-tree-node-content-wrapper:hover:before, .ant-tree.ant-tree-directory>li span.ant-tree-node-content-wrapper:hover:before,
.ant-select-dropdown-menu-item:hover:not(.ant-select-dropdown-menu-item-disabled),
.ant-select-tree li .ant-select-tree-node-content-wrapper:hover,
.ant-table-thead > tr > th,
.ant-calendar-range .ant-calendar-in-range-cell::before {
  background: ${highlightColor} !important;
}
.ant-layout,
.ant-steps-item-finish .ant-steps-item-icon,
body {
  background: ${bodyBg};
}
.ant-dropdown-menu,
.ant-table,
.array-table-addition,
.ant-calendar-decade-panel,
.ant-calendar-year-panel,
.ant-calendar-month-panel,
.ant-calendar-date-panel,
.ant-calendar-input,
.ant-input-number-handler-wrap,
.am-picker-popup,
.am-modal-content,
.gcc-mobile-form,
.am-list-item,
.ant-popover-inner,
.ant-table-placeholder,
.ant-table-body > tr > td,
.ant-select-dropdown,
.ant-radio-inner,
.dynamic-theme,
.ant-btn,
.ant-modal-header,
.ant-modal-content,
.ant-input,
.ant-input-number-input-wrap,
.ant-select-selection,
.ant-checkbox-inner,
.ant-calendar,
.ant-select-dropdown-menu-item-active:not(.ant-select-dropdown-menu-item-disabled),
.ant-card {
  background: ${background} !important;
  color: ${color} !important;
}
.ant-tree-title,
.dynamic-color {
  color: ${color} !important;
}
.ant-dropdown-menu-item, .ant-dropdown-menu-submenu-title,
.ant-upload-list,
.ant-upload-list-item-info .anticon-loading, .ant-upload-list-item-info .anticon-paper-clip,
.ant-upload-list-item-card-actions .anticon,
.ant-calendar-decade-panel-decade,
.ant-rate-star-first, .ant-rate-star-second,
.ant-calendar-month-panel-header .ant-calendar-month-panel-century-select,
.ant-calendar-month-panel-header .ant-calendar-month-panel-decade-select,
.ant-calendar-month-panel-header .ant-calendar-month-panel-year-select,
.ant-calendar-month-panel-header .ant-calendar-month-panel-month-select,
.ant-calendar-month-panel-month,
.ant-calendar-year-panel-header .ant-calendar-year-panel-century-select,
.ant-calendar-year-panel-header .ant-calendar-year-panel-decade-select,
.ant-calendar-year-panel-header .ant-calendar-year-panel-year-select,
.ant-calendar-year-panel-header .ant-calendar-year-panel-month-select,
.ant-calendar-year-panel-year,
.ant-calendar-header .ant-calendar-century-select,
.ant-calendar-header .ant-calendar-decade-select,
.ant-calendar-header .ant-calendar-year-select,
.ant-calendar-header .ant-calendar-month-select,
.ant-select-dropdown-menu-item,
.am-modal.am-modal-operation .am-modal-content .am-modal-button,
.am-textarea-control textarea,
.am-list-item .am-input-control input,
.am-picker-col-item,
.am-list-item .am-list-line .am-list-content,
.gcc-mobile-form-label,
.anticon,
.ant-steps-item-wait .ant-steps-item-icon>.ant-steps-icon,
.ant-form,
.ant-table,
.ant-tree,
.ant-tree-child-tree .ant-tree-node-content-wrapper .ant-tree-title, .ant-tree-switcher .ant-tree-switcher-icon,
.ant-tree li .ant-tree-node-content-wrapper,
.ant-popover-message-title,
.ant-table-thead > tr > th,
.ant-table-body > tr > th,
.ant-empty-description,
.ant-tabs,
.preview-text,
.ant-select-tree-title,
.ant-calendar-date,
.ant-radio-wrapper,
.ant-form-item-label > label,
.ant-modal-title,
.ant-card-extra,
.ant-modal-close,
.ant-checkbox-wrapper,
.ant-steps-item-process > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-description,
.ant-steps-item-finish > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-title {
  color: ${color};
}
.ant-rate .anticon { color: inherit; }
.ant-calendar-decade-panel-last-century-cell .ant-calendar-decade-panel-decade,
.ant-calendar-decade-panel-next-century-cell .ant-calendar-decade-panel-decade,
.ant-calendar-year-panel-last-decade-cell .ant-calendar-year-panel-year,
.ant-calendar-year-panel-next-decade-cell .ant-calendar-year-panel-year {
  color: rgba(255,255,255, 0.45);
}
.am-input-label,
.am-list-header,
.dynamic-title,
.ant-steps-item-wait>.ant-steps-item-container>.ant-steps-item-content>.ant-steps-item-title,
.ant-steps-item-process > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-title,
.ant-card-head-title {
  color: ${strongColor} !important;
}
.ant-calendar-picker-clear {
  color: ${background};
}
.am-picker-col-mask {
  /* background-image: linear-gradient(to bottom, ${highlightColor}, ${background}), linear-gradient(to top, ${highlightColor}, ${background}); */
  display: none;
}
.ant-input,
.ant-btn,
.ant-input-number,
.ant-select-selection,
.ant-select-dropdown,
.ant-select-dropdown-menu-vertical {
  border-radius: 2px;
  border: 1px solid #33506B;
}

.ant-radio-inner,
.ant-checkbox-inner {
  border-color: #33506b;
}
.ant-dropdown-menu,
.ant-card-bordered {
  border: ${borderValue};
}
.ant-btn-disabled, .ant-btn.disabled, .ant-btn[disabled], .ant-btn-disabled:hover, .ant-btn.disabled:hover, .ant-btn[disabled]:hover, .ant-btn-disabled:focus, .ant-btn.disabled:focus, .ant-btn[disabled]:focus, .ant-btn-disabled:active, .ant-btn.disabled:active, .ant-btn[disabled]:active, .ant-btn-disabled.active, .ant-btn.disabled.active, .ant-btn[disabled].active,
.ant-table-thead > tr > th,
.ant-table-tbody > tr > td {
  border-color: ${borderColor};
}
.ant-card-head,
.ant-modal-header {
  border-bottom: ${borderValue};
}
.ant-modal-footer {
  border-top: ${borderValue};
}
.ant-calendar-date:hover,
.ant-calendar-selected-day .ant-calendar-date {
  background: #bae7ff;
  color: #608EFF;
}
.ant-progress-inner,
.ant-divider {
  background-color: ${borderColor};
}
`;
}
if (BUSINESS_MODE === '1') {
  if (location.search.indexOf('noTheme') < 0) {
    // updateTheme('rgba(255,255,255,.6)','rgba(255,255,255,.8)', '#013460','rgba(1, 52, 96, .6)');
    updateTheme('rgba(255,255,255,.6)','rgba(255,255,255,.8)', '#013460', '#01294d');
  }
}
// window.updateTheme = updateTheme;
const sendToParent = (paylod, origin = window.origin) => {
  if (window.parent !== window) {
    window.parent.postMessage(paylod, origin);
  }
}

const phoneProcessHandleUrlMap = {
  'addSignVisible': '/embedded/phone/todo-detail/add-sign',
};

const getPhoneUrlForHandle = (actionName, taskId, applyUserId) => {
  const url = phoneProcessHandleUrlMap[actionName];
  if (!url) { return url; };
  return `${url}?taskId=${taskId}&applyUserId=${applyUserId}`;
}

export {
  getUuid,
  getSubFieldCol,
  delay,
  getViewPortHeight,
  goToUrl,
  openNotificationWithIcon,
  setActiveMenu,
  omit,
  getOrgArrs,
  getOrgName,
  updateNoticeUser,
  transformEditorToFormily,
  getCardChildProperties,
  isPhone,
  updateTheme,
  sendToParent,
  openNotificationWithIconPhone,
  getPhoneUrlForHandle,
}